#include "editor_view.h"

EditorView::EditorView(EditorScene *scene, QWidget *parent):QGraphicsView(parent)
{
    this->editorScene = scene;
    this->temp_edge = new NodeTempEdge(QPointF(0,0),QPointF(0,0));
    //this->dataScene = new EditorScene();
    this->setScene(this->editorScene);

    this->setRenderHints(QPainter::Antialiasing | QPainter::HighQualityAntialiasing |
                         QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
    this->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);  // 防止画线的bug？
    this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    this->setTransformationAnchor(QGraphicsView::AnchorUnderMouse); //设置锚点
    this->setDragMode(QGraphicsView::RubberBandDrag);  // 框选

    this->input_node_index = -1;
    this->input_socket_index = -1;
    this->output_node_index = -1;
    this->output_socket_index = -1;
}

EditorView::~EditorView()
{
    delete editorScene;
    delete edge;
    delete temp_edge;
    this->node.clear();
    this->edges.clear();
}


void EditorView::mousePressEvent(QMouseEvent *event){
    if(event->button()== Qt::MiddleButton){
        this->middleMouseButtonPress(event);
    }
    else if(event->button() == Qt::LeftButton){
        leftMouseButtonPress(event);
    }
    else if(event->button() == Qt::RightButton){
        RightMouseButtonPress(event);
    }
    else{
        QGraphicsView::mousePressEvent(event);
    }
}

void EditorView::mouseReleaseEvent(QMouseEvent *event){
    if(event->button()== Qt::MiddleButton){
        this->middleMouseButtonRelease(event);
    }
    else if(event->button() == Qt::LeftButton){
        LeftMouseButtonRelease(event);
    }
    else if(event->button() == Qt::RightButton){
        RightMouseButtonRelease(event);
    }
    else{
        QGraphicsView::mouseReleaseEvent(event);
    }
}

void EditorView::middleMouseButtonPress(QMouseEvent *event){
    QMouseEvent *releaseEvent =new QMouseEvent(QEvent::MouseButtonPress, event->localPos(),
                                           event->screenPos(), Qt::LeftButton, Qt::NoButton, event->modifiers());
    QGraphicsView::mouseReleaseEvent(releaseEvent);
    this->setDragMode(QGraphicsView::ScrollHandDrag);  // 设置鼠标形状
    QMouseEvent *fakeEvent = new QMouseEvent(event->type(),event->localPos(),event->screenPos(),
                                             Qt::LeftButton, event->buttons() | Qt::LeftButton ,event->modifiers());
    QGraphicsView::mouseReleaseEvent(fakeEvent);

    delete releaseEvent;
    delete fakeEvent;
}

void EditorView::middleMouseButtonRelease(QMouseEvent *event){
    QMouseEvent *fakeEvent = new QMouseEvent(event->type(),event->localPos(),event->screenPos(),
                                             Qt::LeftButton, event->buttons() | Qt::LeftButton ,event->modifiers());
    QGraphicsView::mouseReleaseEvent(fakeEvent);
    this->setDragMode(QGraphicsView::RubberBandDrag);

    delete fakeEvent;
}
void EditorView::leftMouseButtonPress(QMouseEvent *event)
{
    QGraphicsView::mousePressEvent(event);

    QPoint pos = event->pos();
    QPointF obj_pos;
    //ContainsTest(pos);

    //qDebug()<<typeid(obj).name();
    obj = this->itemAt(pos);
    // 如果是obj则能够转换成功，那么就是要找的QGraphicsitem
    if(item = dynamic_cast<QGraphicsItem*>(obj)){
        //qDebug()<<"type:"<<obj->type();
        if(obj->type()==Type_NodeSocket){
            //qDebug()<<obj->isUnderMouse();
            obj_pos = obj->pos();
            obj_pos = mapToScene(pos);
            QuerySocket(obj_pos);

            this->temp_edge = new NodeTempEdge(obj_pos,obj_pos);
            //this->temp_edge->SetStartPos(mapFromParent(obj_pos.toPoint()));
            //this->temp_edge->SetEndPos(mapFromParent(obj_pos.toPoint()));
            this->editorScene->addItem(temp_edge);
            //qDebug()<<n++<<"add temp edge";
            is_temp_alive = true;
            return;
        }
    }

    //shift 加选

    //    if(event->modifiers() & Qt::ShiftModifier){
    //        event->ignore();
    //        QMouseEvent *fakeEvent = new QMouseEvent(QEvent::MouseButtonPress,event->localPos(),event->screenPos(),
    //                                                 Qt::LeftButton, event->buttons() | Qt::LeftButton ,
    //                                                 event->modifiers() | Qt::ControlModifier);
    //        QGraphicsView::mousePressEvent(fakeEvent);
    //        qDebug()<<"shift";
    //        return;
    //    }



}
//TODO 增加连线模式以无需任何release都计算是否连线
void EditorView::LeftMouseButtonRelease(QMouseEvent *event)
{
    QGraphicsView::mouseReleaseEvent(event);
    if(is_temp_alive){
        this->temp_edge->hide();
        this->editorScene->removeItem(this->temp_edge);
        //qDebug()<<this->editorScene->items().count();
        //this->scene()->views().count();
        is_temp_alive = false;
    }


    QPoint pos = event->pos();
    QPointF obj_pos;
    //QGraphicsItem *obj = this->itemAt(pos);
    //QGraphicsItem *item;


    // 如果是obj则能够转换成功，那么就是要找的QGraphicsitem
    obj = this->itemAt(pos);
    if(item = dynamic_cast<QGraphicsItem*>(obj)){
        //qDebug()<<"type:"<<obj->type();
        if(obj->type()==Type_NodeSocket){
            obj_pos = obj->pos();
            obj_pos = mapToScene(pos);
            QuerySocket(obj_pos);
            // 不允许自己连自己
            if(output_node_index==input_node_index)
                return;
            // 不允许非法连接
            if(output_node_index==-1 || output_socket_index==-1 || input_node_index==-1 || input_socket_index==-1)
                return;
            qDebug()<<output_node_index<<output_socket_index<<input_node_index<<input_socket_index;
            this->AddEdge(output_node_index,output_socket_index,input_node_index,input_socket_index);

            return;

        }
    }
    this->update();


    //shift 加选
//    if(event->modifiers() & Qt::ShiftModifier){
//        event->ignore();
//        QMouseEvent *fakeEvent = new QMouseEvent(event->type(),event->localPos(),event->screenPos(),
//                                                 Qt::LeftButton, Qt::NoButton ,
//                                                 event->modifiers() | Qt::ControlModifier);
//        QGraphicsView::mouseReleaseEvent(fakeEvent);
//        qDebug()<<"shift";
//        return;
//    }

    //更新节点数据在MouseRelease？
    QueryNodeDate();

}
void EditorView::RightMouseButtonPress(QMouseEvent *event)
{
    QGraphicsView::mousePressEvent(event);
}
void EditorView::RightMouseButtonRelease(QMouseEvent *event)
{
    QGraphicsView::mouseReleaseEvent(event);
}

void EditorView::mouseMoveEvent(QMouseEvent *event)
{
    if(is_temp_alive){
        QPointF pos = mapToScene(event->pos());

        this->temp_edge->SetEndPos(pos);
        this->editorScene->update();
    }
    QGraphicsView::mouseMoveEvent(event);
}

void EditorView::keyPressEvent(QKeyEvent *event)
{
    if((event->modifiers()== Qt::ShiftModifier) && event->key() == Qt::Key_A){
        this->addNodeItem(number++,1);
        return;
    }
    if((event->modifiers()== Qt::ShiftModifier) && event->key() == Qt::Key_S){
        this->addNodeItem(number++,0);
        return;
    }
    if((event->modifiers()== Qt::ShiftModifier) && event->key() == Qt::Key_Z){
        this->addNodeItem(number++,2);
        return;
    }
    if((event->modifiers()== Qt::ShiftModifier) && event->key() == Qt::Key_X){
        this->addNodeItem(number++,3);
        return;
    }
    if((event->modifiers()== Qt::ShiftModifier) && event->key() == Qt::Key_C){
        this->addNodeItem(number++,4);
        return;
    }
    if((event->modifiers()== Qt::ShiftModifier) && event->key() == Qt::Key_V){
        this->addNodeItem(number++,5);
        return;
    }
    if((event->modifiers()== Qt::ShiftModifier) && event->key() == Qt::Key_Q){
        this->addNodeItem(number++,9);
        return;
    }

    if(event->key() == Qt::Key_Delete){
//        qDebug()<<"node count before"<<this->node.length();
//        qDebug()<<"edge count before"<<this->edges.length();
//        qDebug()<<"item count before"<<this->editorScene->items().length();
        QList<QGraphicsItem*> item_list = this->editorScene->selectedItems();
        for(int i=0;i<item_list.length();i++){
            //qDebug()<<item_list.length();
            if(item_list[i]->type() >= Type_NodeItem && item_list[i]->type() <= Type_NodeItemOutput
                    || item_list[i]->type() ==Type_NodeGraphics ){
                // 从场景中删除节点
                this->editorScene->removeItem(item_list[i]);

                // 从内存中删除节点
                for(int j=0;j<this->node.length();j++){
                    if(item_list[i] == NodeToItem(this->node[j])){

                        // 删除相关的连线
//                        for(int k=0;k<this->node.length();k++){
//                            for(int ki=0;ki<this->node[k]->input.length();ki++){
//                                if(this->node[j])
//                            }
//                            for(int ko=0;ko<this->node[k]->output.length();ko++){

//                            }
//                        }
                        delete this->node[j];
                        this->node[j] = NULL;
                        this->node.removeOne(this->node[j]);
                    }
                }

            }
// Q:removeItem edge remain the edge
            if(item_list[i]->type() == Type_NodeEdge){  // 删除连线
                item_list[i]->hide();  // 为避免渲染bug使用hide

                // 从场景中删除连线
                this->editorScene->removeItem(item_list[i]);

                // 从内存中删除连线
                for(int j=0;j<this->edges.length();j++){
                    if(item_list[i] == EdgeToItem(this->edges[j])){
                        qDebug()<<"reset socket connect";
                        this->edges[j]->end_socket->isConnected = false;
                        this->edges[j]->end_socket->node_index = -1;

                        delete this->edges[j];
                        this->edges[j] = NULL;
                        this->edges.removeOne(this->edges[j]);
                    }
                }
            }


        }

//        qDebug()<<"node count after"<<this->node.length();
//        qDebug()<<"edge count after"<<this->edges.length();
//        qDebug()<<"item count after"<<this->editorScene->items().length();


    }
    QGraphicsView::keyPressEvent(event);
}

void EditorView::wheelEvent(QWheelEvent *event)
{
    // the factor of zoom
    float zoomOutFactor = 1 / this->zoomInFactor;
    float zoomFactor;
    // store the scene pos
    QPointF *oldPos = new QPointF(this->mapToScene(event->pos()));
    Q_UNUSED(oldPos);
    if(event->angleDelta().y() > 0){
        zoomFactor = zoomInFactor;
        zoom += zoomStep;
    }
    else{
        zoomFactor = zoomOutFactor;
        zoom -= zoomStep;
    }

    BOOLEAN clamped = false;  // 放缩的限制
    if(this->zoom < zoomRange[0]){
        this->zoom = zoomRange[0];
        clamped = true;
    }
    if(this->zoom > zoomRange[1]){
        this->zoom = zoomRange[1];
        clamped = true;
    }

    if(!clamped || !this->zoomClamp)
        this->scale(zoomFactor,zoomFactor);  // set scene scale

    //TODO 清晰化
    /*
    QPointF *newPos = new QPointF(this->mapToScene(event->pos()));
    QPointF *delta = new QPointF(*newPos - *oldPos);
    this->translate(delta->x(),delta->y());
    this->translate(100.0,100.0);
    */


   // event->accept();
}
void EditorView::QuerySocket(QPointF pos)
{
    //qDebug()<<"Query"<<pos;
    for(int i=0;i<this->node.length();i++){
        for(int j=0;j<this->node[i]->input.length();j++){
            if(this->node[i]->input[j]->contains(pos)){
                if(output_ready){
                    input_node_index = this->node[i]->index;
                    input_socket_index = this->node[i]->input[j]->index;
                    output_ready = false;

                    //qDebug()<<"QuerySocket input"<<input_node_index<<input_socket_index;
                }
                return;
            }
        }
        for(int j=0;j<this->node[i]->output.length();j++){
            if(this->node[i]->output[j]->contains(pos)){
                output_node_index = this->node[i]->index;
                output_socket_index = this->node[i]->output[j]->index;
                output_ready = true;
                //qDebug()<<"QuerySocket output"<<output_node_index<<output_socket_index;

                return;
            }
        }
    }
}

NodeScene *EditorView::DeleteNode(QPointF pos)
{
    for(int i=0;i<this->node.length();i++){
        for(int j=0;j<this->node[i]->input.length();j++){
            if(this->node[i]->input[j]->contains(pos)){
                //remove edge
                return this->node[i];
            }
        }
        for(int j=0;j<this->node[i]->output.length();j++){
            if(this->node[i]->output[j]->contains(pos)){
                return this->node[i];
            }
        }
    }
    return NULL;
}

void EditorView::DeleteNode(NodeScene node)
{
    for(int i=0;i<this->node.length();i++){
        if(node.index == this->node[i]->index){
            this->node.remove(i);
            return;
        }
    }
}

void EditorView::addNodeItem(int index)
{
    NodeScene *nodeScene = new NodeScene(index);
    nodeScene->SetIndex(index);
    // output = last input = node now
    for(int i=0;i<nodeScene->output.length();i++){
        nodeScene->output[i]->node_index = nodeScene->index;
    }
    for(int i=0;i<nodeScene->input.length();i++){
        nodeScene->input[i]->node_index = -1;
        nodeScene->input[i]->out_socket_index = -1;
        //nodeScene->input[i]->isConnected = false;
    }
    node.push_back(nodeScene);

    this->editorScene->addItem(node[node.length()-1]->item);
    //delete nodeScene

}

void EditorView::addNodeItem(int index, int type)
{
    NodeScene *nodeScene = new NodeScene(index,type);
    nodeScene->SetIndex(index);
    // output = last input = node now
    for(int i=0;i<nodeScene->output.length();i++){
        nodeScene->output[i]->node_index = nodeScene->index;
    }
    for(int i=0;i<nodeScene->input.length();i++){
        nodeScene->input[i]->node_index = -1;
        nodeScene->input[i]->out_socket_index = -1;
        //nodeScene->input[i]->isConnected = false;
    }

// 在鼠标位置添加节点,全屏时才生效
    //nodeScene->item->setPos(mapToScene(QCursor::pos()));
    node.push_back(nodeScene);

    this->editorScene->addItem(node[node.length()-1]->item);
}

void EditorView::SetNodeTitle(int index, QString title)
{
    for(int i=0;i<node.length();i++){
        if(node[i]->index == index){
            node[i]->SetItemTitle(title);
        }
    }
}

void EditorView::AddEdge(int start_node_index, int start_socket_index, int end_node_index, int end_socket_index)
{
    NodeSocket *temp1 = new NodeSocket();
    NodeSocket *temp2 = new NodeSocket();
    NodeScene *node1 = new NodeScene(-1);
    NodeScene *node2 = new NodeScene(-1);
    for(int i=0;i<node.length();i++){
        // 从output出，连线到input里

        if(node[i]->index == start_node_index){
            for(int j=0;j<node[i]->output.length();j++){
                if(node[i]->output[j]->index == start_socket_index){
                    temp1 = node[i]->output[j];
                    node1 = node[i];
                    //item1 = node[i]->item;
                }
            }
        }
        //TODO: 去重
        if(node[i]->index == end_node_index){
            for(int j=0;j<node[i]->input.length();j++){
                if(node[i]->input[j]->index == end_socket_index){
                    temp2 = node[i]->input[j];
                    // 输入socket只能容纳一个连线

                    if(temp2->isConnected){
                        qDebug()<<"连线已经存在";
                        return;
                    }
                    temp2->isConnected = true;
                    // output = last input = node now
                    // temp2 是输入节点，temp1是输出节点
//重复问题node_index/out_socket_index
                    temp2->node_index = temp1->node_index;
                    temp2->out_socket_index = temp1->index;

                    node2 = node[i];
                    //item2 = node[i]->item;
                }
            }
        }
    }
    //TODO这里指定父级可能有移动的问题
    //this->edge = new NodeEdge(temp1,temp2,item);
    this->edge = new NodeEdge(node1,node2,temp1,temp2);
    this->edge->setZValue(-1);
    this->edge->end_socket->node_index = this->edge->start_node->index;
    this->edge->end_socket->out_socket_index = this->edge->start_socket->index;
    this->edges.append(this->edge);
    //item has already been added to this scene?
    this->editorScene->addItem(this->edge);



    QueryNodeDate();
}

void EditorView::RemoveEdge(int start_node_index, int start_socket_index, int end_node_index, int end_socket_index)
{
    //TODO 检测edge是否存在，不存在的处理
    //TODO edges删除
    qDebug()<<"remove edge by index";
    NodeEdge *remove_edge = new NodeEdge();
    for(int i=0;i<edges.length();i++){
        if(edges[i]->start_node->index == start_node_index &&
                edges[i]->end_node->index == end_node_index &&
                edges[i]->start_socket->index == start_socket_index &&
                edges[i]->end_socket->index == end_socket_index)
        {
            remove_edge = edges[i];
            remove_edge->end_socket->isConnected = false;  // 置为未连接
            remove_edge->end_socket->node_index = -1;  // 失去连接便没有上一个节点的index
            remove_edge->end_socket->out_socket_index = -1;  // 失去连接便没有上一个socket的index

            qDebug()<<"reset socket connect";
            this->editorScene->removeItem(edges[i]);
            //edges[i]= NULL;
            edges.remove(i);
        }

    }
    this->editorScene->removeItem(remove_edge);
    // 是否需要？以及，为什么delete会导致崩溃？是因为remove_edge = edges[i];，如果delete就会delete掉edges？
    //remove_edge = NULL;
}

QGraphicsItem* EditorView::NodeToItem(NodeScene *node)
{
    QGraphicsItem *item(node->item);
    return item;
}

QGraphicsItem *EditorView::EdgeToItem(NodeEdge *edge)
{
    QGraphicsItem *item(edge);
    return item;
}

void EditorView::UpdateNodeData()
{
    for(int i=0;i<this->node.length();i++){
        for(int j=0;j<this->node[i]->input.length();j++){
            if(this->node[i]->input[j]->isConnected){
                // socket被连接，有数据传送

            }
        }
    }
}

void EditorView::QueryNodeDate()
{
    int node_index;
    bool is;
    NodeScene *out;
    NodeScene *in;
    double value1;
    double value2;
    NumberData indata;
    NumberData outdata;
    NumberData temp;
//TODO 多socket部分
//TODO 优化
    for(int k=0;k<this->node.length();k++){
        qDebug()<<"node index:"<<this->node[k]->index;
    for(int i=0;i<this->node.length();i++){
        //qDebug()<<this->node[i]->item->type();
        for(int j=0;j<this->node[i]->input.length();j++){
            is = this->node[i]->input[j]->isConnected;              // 判断是否被连接上
            if(is){                                                 // 是某节点的第j个socket，传送到data[j]中
                node_index = this->node[i]->input[j]->node_index;   // 获取所属节点的index
                out = node[i];                                      // 数据传送到的节点
                //qDebug()<<node[i]->index<<":"<<node_index;

                for(int n=0;n<this->node.length();n++){             // 寻找数据传送的节点
                    if(node_index == node[n]->index){               // 通过node_index寻找到
                        in = node[n];                               // TODO：不同输出节点输出不同内容
//                        value = in->item->GetData();
//                        out->item->SetData(QString::number(value,10,4));
//                        indata = in->item->GetNumberData();
//                        out->item->SetNumberData(indata);



                        temp = in->item->GetNumberData();
                        qDebug()<<this->node[i]->input[j]->node_index<<this->node[i]->input[j]->out_socket_index<<this->node[i]->input[j]->index;
                        //indata.data[this->node[i]->input[j]->out_socket_index] = temp.data[this->node[i]->input[j]->out_socket_index];
                        value1 = temp.data[this->node[i]->input[j]->out_socket_index];
                        outdata.data[this->node[i]->input[j]->index] = value1;
                        qDebug()<<"transfer"<<outdata.data[0]<<outdata.data[1]<<outdata.data_length;
                        //TODO transfer 数值异常的问题
                        out->item->SetNumberData(outdata);

                    }
                }
            }
        }
    }

    }
    qDebug()<<"------";

}


/*
QDataStream &operator<<(QDataStream &output, const EditorView &view){
//    while(!view.node.empty()){
//        output << view.node.front();
//        view.node.pop // queue
//    }
    for(int i=0;i<view.node.length();i++){
        output << view.node[i];
    }
    for(int j=0;j<view.edges.length();j++){
        output << view.edges[j];
    }
    return output;
}
QDataStream &operator>>(QDataStream &input, EditorView &view){
    while(!input.atEnd()){
        NodeScene node(1);
        // 重载input
        //input >>node;
    }


    return input;
}
*/
